package com.xiaoxin_project.netty;

import com.xiaoxin_project.SpringUtil;
import com.xiaoxin_project.Util.JsonUtils;
import com.xiaoxin_project.enums.MsgActionEnum;
import com.xiaoxin_project.service.UserService;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.handler.codec.http.websocketx.TextWebSocketFrame;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 处理消息的handler
 * TextWebSocketFrame:在netty中是用于为websocket专门处理文本的对象 frame是消息载体
 */
@Component
public class ChatHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    //记录和管理所有客户端的Channel
    public static ChannelGroup users = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);


    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {

        Channel currentChannel = ctx.channel();

        //1.获取客户端发来的消息
        String content = msg.text();
        //转换消息
        DataContent dataContent = JsonUtils.jsonToPojo(content, DataContent.class);
        Integer action = dataContent.getAction();
        //2.判断消息类型，根据不同类型处理不同业务
        if (action == MsgActionEnum.CONNECT.type) {
            //2.1 当websocket第一次open的时候，初始化channel 用户channel与userid关联起来
            String senderId = dataContent.getChatMsg().getSenderId();
            UserChannelRel.put(senderId, currentChannel);

            //测试
            /*for (Channel c : users){
                System.out.println(c.id().asLongText());
            }
            UserChannelRel.output();*/

        } else if (action == MsgActionEnum.CHAT.type) {
            //2.2 聊天类型的消息，聊天记录保存到数据库，同时标记消息的签收状态【未签收】
            ChatMsg chatMsg = dataContent.getChatMsg();
            String msg1 = chatMsg.getMsg();
            String receiverId = chatMsg.getReceiverId();
            String senderId = chatMsg.getSenderId();
            //保存消息到数据库，并且标记为未签收
            UserService userService = (UserService) SpringUtil.getBean("userServiceImpl");
            String msgId = userService.saveMsg(chatMsg);
            chatMsg.setMsgId(msgId);

            DataContent dataContentMsg = new DataContent();
            dataContentMsg.setChatMsg(chatMsg);

            //发送消息
            //从全局关系中获取接收方的channel
            Channel receiverChannel = UserChannelRel.get(receiverId);
            if (receiverChannel == null) {
                //用户离线，推送消息
            } else {
                //当receiverChannel不为空时，从ChannelGroup中去查找对应的Channel是否存在(有该接受用户通道的绑定才能发送消息给接收方)
                Channel findChannel = users.find(receiverChannel.id());
                if (findChannel != null) {
                    //用户在线
                    receiverChannel.writeAndFlush(new TextWebSocketFrame(JsonUtils.objectToJson(dataContentMsg)));
                } else {
                    //用户离线 推送消息
                }
            }

        } else if (action == MsgActionEnum.SIGNED.type) {
            //2.3 签收消息类型，针对具体的消息进行签收，修改数据库中对应的消息签收状态【已签收】
            UserService userService = (UserService) SpringUtil.getBean("userServiceImpl");
            //需要去签收的消息id 逗号间隔
            String msgIdsStr = dataContent.getExtand();
            String[] msgIds = msgIdsStr.split(",");
            List<String> msgIdList = new ArrayList<>();
            for (String mid : msgIds) {
                if (StringUtils.isNotBlank(mid)) {
                    msgIdList.add(mid);
                }
            }
            System.out.println(msgIdList.toString());
            System.out.println(msgIdList);

            if (msgIdList != null && !msgIdList.isEmpty() && msgIdList.size() > 0) {
                //批量签收
                userService.updateMsgSigned(msgIdList);
            }

        } else if (action == MsgActionEnum.KEEPALIVE.type) {
            //2.4 心跳类型的消息
            System.out.println("收到来自channel为:【"+currentChannel+"】的心跳包");
        }


    }

    /**
     * 当客服端连接到服务端后获取客户端的channel并放到ChannelGroup中去并进行管理
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        users.add(ctx.channel());
    }

    /**
     * 当客户端连接关闭时移除该用户端管理的Channel
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        String channelId = ctx.channel().id().asShortText();
        //System.out.println("客户端被移除 channelId为："+ channelId);
        users.remove(ctx.channel());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        //发生异常后关闭连接（关闭channel），随后从ChannelGroup中移除
        ctx.channel().close();
        users.remove(ctx.channel());
    }
}
